﻿using System;
using System.Collections.Generic;
using System.Text;
using GeometryCSharp;
using AGHFiraPlayer;
using System.IO;

namespace AGHFiraPlayer.Strategies.StrategiesImpl
{
    class SimpleShotStrategy : AbstractStrategy
        {
        //to powoduje problemy
        private int CALCULATE_STEPS = 100;

        private double TOO_LONG = SimpleFunctions.TOO_LONG;
        private Point2D MIDDLE_OF_GOAL = new Point2D(Predicator.pitchArea.Right, Predicator.pitchArea.Height/2.0);
        private Point2D shotSpot = null;
        private Vector2D toGoal;
        private double eta;

        private const double CLEAR_WAY_FACTOR = 50;
        private const double TIME_FACTOR = 50;
        
        public SimpleShotStrategy(ref AGHDriver driver)
        {
            this.driver = driver;
            involvedRobots = new List<RobotController>(1);
            type = StrategyType.Offensive;
        }

        private Point2D calculateShotPoint(RobotController robot)
        {
            eta = 0.0;
            
            Point2D ballPosition;
            Point2D shotPoint=null;
            while (shotPoint==null) {
   
                eta += 0.05;
                if (eta > TOO_LONG)
                {
                    break;
                }
                ballPosition = Predicator.GetBallPosition(eta);
                toGoal = new Vector2D(ballPosition, MIDDLE_OF_GOAL);
                toGoal.Normalize();
                BezierCurve bc = BezierCurveDriver.calculateBezzierCurve(robot.robotState, ballPosition, PotencialDriver.maxVelocity, toGoal);
                double distance;
                if (bc == null)
                {
                    continue;
                }
                else
                {
                    distance = bc.calculateLength(CALCULATE_STEPS);
                    double calculatedEta = distance / PotencialDriver.maxVelocity;
                    if (calculatedEta < eta)
                    {
                        shotPoint = ballPosition;
                    }
                }

            }
            return shotPoint;
        }
        private void resetValues() {
            shotSpot = null;
            eta = 0;
            toGoal = null;
            
        }
        override public int applicabilityLevel(ref List<IStrategy> choosenStrategies) {
            resetValues();
            Point2D tmpShotSpot;
            double maxScore = -5;
            double timeFactor = -1 * (TIME_FACTOR + CLEAR_WAY_FACTOR);
            foreach (RobotController robot in driver.Robots)
            {
                if (!robot.isUsedInStrategy)
                {
                    if (involvedRobots.Count == 0)
                    {
                        involvedRobots.Add(robot);
                    }
                    foreach (AbstractStrategy strategy in choosenStrategies) {
                        if (strategy.getStrategyType() == StrategyType.Offensive || strategy.getStrategyType() == StrategyType.Passing)
                        {
                            return -1;
                        }

                    }

                    
                    involvedRobots.Add(robot);
                    //CLEAR_WAY_FACTOR
                    //number from 200 to -200 :)
                    double positionFactor = SimpleFunctions.judgePosition(robot)*CLEAR_WAY_FACTOR/SimpleFunctions.MAGIC_NUMBER;
                    //double positionFactor = 100
                    //TIME_FACTOR
                    tmpShotSpot = calculateShotPoint(robot);

                    timeFactor = -1 * (TIME_FACTOR + CLEAR_WAY_FACTOR);
                    if (tmpShotSpot != null)
                    {
                        timeFactor = ((TOO_LONG - eta) / TOO_LONG) * TIME_FACTOR;
                    }
                    if ((timeFactor + positionFactor) > maxScore)
                    {
                        shotSpot = tmpShotSpot;
                        maxScore = timeFactor + positionFactor;
                        involvedRobots.Clear();
                        involvedRobots.Add(robot);
                    }
                    
                }
            }
           
            return (int)maxScore;
            
            
        }
        
        override public void execute()
        {
            shotSpot = calculateShotPoint(involvedRobots[0]);
            if (shotSpot != null)
            {
                toGoal = new Vector2D(shotSpot, MIDDLE_OF_GOAL);
                toGoal.Normalize();
                BezierCurve bc = BezierCurveDriver.calculateBezzierCurve(involvedRobots[0].robotState, shotSpot, PotencialDriver.maxVelocity, toGoal);

                double distance;
                if (bc != null)
                {
                    distance = bc.calculateLength(CALCULATE_STEPS);
                    double calculatedVelocity = distance / eta;
                    
                    BezierCurveDriver.driveWithVelocityVector(involvedRobots[0].robotState, shotSpot.x, shotSpot.y, calculatedVelocity, toGoal);
                    Point2D robotPosition = new Point2D(involvedRobots[0].robotState.x, involvedRobots[0].robotState.y);
                }
            }
            return;
      
                   
        }   
    }
}
